#include "StdAfx.h"
#include <windows.h>
#include <tchar.h>
#include <crtdbg.h>
#include "IPC.h"

std::string CIPC::g_szIPCSharedMMF = _T("{34F673E0-878F-11D5-B98A-00B0D07B8C7C}");
std::string CIPC::g_szIPCMutex = _T("{34F673E1-878F-11D5-B98A-00B0D07B8C7C}");

CIPC::CIPC() : m_hFileMap(NULL), m_hMutex(NULL)
{
}


CIPC::~CIPC()
{
	CloseIPCMMF();
	Unlock();
}

bool CIPC::CreateIPCMMF(void)
{
	bool bCreated = false;

	do 
	{
		if( m_hFileMap != NULL )
		{
			break;
		}

		// Create an in-memory 4KB memory mapped file to share data
		m_hFileMap = CreateFileMapping((HANDLE)0xFFFFFFFF,
			NULL,
			PAGE_READWRITE,
			0,
			4096,
			g_szIPCSharedMMF.c_str());

		if(m_hFileMap != NULL)
		{
			bCreated = true;
		}

	} while( 0 );
		
	return bCreated;
}

bool CIPC::OpenIPCMMF(void)
{
	bool bOpened = false;

	do 
	{
		if(m_hFileMap != NULL)
		{
			bOpened = true;
			break;
		}

		m_hFileMap = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,
			FALSE,
			g_szIPCSharedMMF.c_str());

		if( m_hFileMap != NULL )
		{
			bOpened = true;
		}

	} while( 0 );
		

	return bOpened;
}

void CIPC::CloseIPCMMF(void)
{
	do 
	{
		if( m_hFileMap != NULL )
		{
			CloseHandle(m_hFileMap), m_hFileMap = NULL;
		}

	} while( 0 );

}

bool CIPC::ReadIPCMMF(LPBYTE pBuf, DWORD &dwBufSize)
{
	bool bSuccess = false;
	do 
	{
		if( pBuf == NULL )
		{
			break;
		}

		if( m_hFileMap == NULL )
		{
			break;
		}
		DWORD dwBaseMMF = (DWORD)MapViewOfFile(m_hFileMap,
			FILE_MAP_READ | FILE_MAP_WRITE,
			0, 0, 0);
		if( dwBaseMMF == NULL )
		{
			break;
		}

		// The first DWORD in the MMF contains the size of the data
		DWORD dwSizeofInBuf = dwBufSize;
		CopyMemory(&dwBufSize, (LPVOID)dwBaseMMF, sizeof(DWORD));

		if( dwSizeofInBuf != 0 )
		{
			if(dwBufSize > dwSizeofInBuf)
			{
				bSuccess = false;
				break;
			}
			else
			{
				CopyMemory(pBuf, (LPVOID)(dwBaseMMF + sizeof(DWORD)), dwBufSize);
			}
		}

		BOOL b = UnmapViewOfFile((LPVOID)dwBaseMMF);
		if( !b )
		{
			bSuccess = false;
			break;
		}
		bSuccess = true;

	} while( 0 );
	
	return bSuccess;
}

bool CIPC::WriteIPCMMF(const LPBYTE pBuf, const DWORD dwBufSize)
{
	bool bSuccess = false;

	do 
	{
		if( pBuf == NULL )
		{
			break;
		}
		if( m_hFileMap == NULL )
		{
			break;
		}

		DWORD dwBaseMMF = (DWORD)MapViewOfFile(m_hFileMap,
			FILE_MAP_READ | FILE_MAP_WRITE,
			0, 0, 0);
		if( dwBaseMMF == NULL )
		{
			break;
		}

		// The first DWORD in the MMF contains the size of the data
		CopyMemory((LPVOID)dwBaseMMF, &dwBufSize, sizeof(DWORD));
		CopyMemory((LPVOID)(dwBaseMMF + sizeof(DWORD)), pBuf, dwBufSize);

		BOOL b = UnmapViewOfFile((LPVOID)dwBaseMMF);
		if( !b )
		{
			break;
		}

		bSuccess = true;

	} while( 0 );

	return bSuccess;
}

bool CIPC::Lock(void)
{
	bool bLocked = false;

	do 
	{
		// First get the handle to the mutex
		m_hMutex = CreateMutex(NULL, FALSE, g_szIPCMutex.c_str());
		if(m_hMutex != NULL)
		{
			// Wait to get the lock on the mutex
			if(WaitForSingleObject(m_hMutex, INFINITE) == WAIT_OBJECT_0)
			{
				bLocked = true;
			}
		}

	} while( 0 );

	return bLocked;
}

void CIPC::Unlock(void)
{
	do 
	{
		if(m_hMutex != NULL)
		{
			ReleaseMutex(m_hMutex);
			CloseHandle(m_hMutex);
			m_hMutex = NULL;
		}

	} while( 0 );
}
